<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2024/4/10
 * Time: 12:01
 */

namespace plugin\admin\app\logic\queue;


use plugin\admin\app\logic\BaseLogic;
use plugin\admin\app\model\ai\AiCommandModel;
use plugin\admin\app\model\font\FontModel;
use plugin\admin\app\model\image\ImageCommandPlanModel;
use plugin\admin\app\model\novel\NovelChapterPartModel;
use plugin\admin\app\model\plan\PromotionPlanModel;
use plugin\admin\app\model\queue\AiImageRequestQueueModel;
use plugin\admin\app\model\user\UserNovelChapterPartModel;
use plugin\admin\app\model\user\UserPromotionPlanModel;
use support\Request;
use support\Response;

class QueueLogic extends BaseLogic
{
    protected static $instance;

    public function __construct()
    {
        $this->model = new AiImageRequestQueueModel();
    }

    public static function getInstance()
    {
        //        if(is_object(self::$instance)){
//            return self::$instance;
//        }

        return new self();
    }

    public function select(Request $request): Response
    {
        $source = $request->input('source');
        $partid = $request->input('partid');
        if($source && $partid){
            $source = $source.'_'.$partid;
            $request->inputSet('source',$source);
        }elseif($source){
            $request->inputSet('source',['like',$source]);
        }elseif($partid){
            $request->inputSet('source',['like',$partid]);
        }

        $stauts = $request->input('status');
        if($stauts==3){
            $request->inputSet('status',['>=',3]);
        }
        $field = $request->input('field');
        if($field==false){
            $request->inputSet('field','add_time');
            $request->inputSet('order','desc');
        }

        return parent::select($request);
    }

    protected function doSelect(array $where, string $field = null, string $order = 'desc')
    {
        $model = parent::doSelect($where, $field, $order);
        if(\request()->input('use_type')=='user'){
            $model = $model->where('source', 'like', "user_%");
        }elseif(\request()->input('use_type')=='admin'){
            $model = $model->where('source', 'like', "admin_%");
        }elseif(\request()->input('use_type')=='cron'){
            $model = $model->where('source', 'like', "cron_%");
        }
        return $model;
    }

    protected function formatNormal($items, $total): Response
    {
        $partids = [];
        foreach($items as &$val){
            $sources = explode('_',$val['source']);

            $val['partid'] = $sources[count($sources)-1];
            if(!is_numeric($val['partid'])){
                $val['partid'] = 0;
            }
           if(strpos($val['source'],'admin_plan_part_image_edit')!==false){
               $val['type'] = 'admin';
               $val['source_name'] = '后台片段生图';
           }elseif(strpos($val['source'],'admin_batch_image_test')!==false){
               $val['type'] = 'admin';
               $val['source_name'] = '后台AI生图调试';
           }elseif(strpos($val['source'],'admin_plan_role_image_view')!==false){
               $val['type'] = 'admin';
               $val['source_name'] = '后台角色生图预览';
           }elseif(strpos($val['source'],'admin_plan_part_view_image')!==false){
               $val['type'] = 'admin';
               $val['source_name'] = '后台AI分段生图';
           }elseif(strpos($val['source'],'admin_plan_part_image_view_image')!==false){
               $val['type'] = 'admin';
               $val['source_name'] = '后台AI分段图生图';
           }elseif(strpos($val['source'],'cron_plan_part_image_save')!==false){
               $val['type'] = 'cron';
               $val['source_name'] = '脚本分段预生图';
           }elseif(strpos($val['source'],'user_plan_part_image_view_batch')!==false){
               $val['type'] = 'user';
               $val['source_name'] = '用户批量生图';
           }elseif(strpos($val['source'],'user_plan_part_image_view_one')!==false){
               $val['type'] = 'user';
               $val['source_name'] = '用户重新生图';
           }elseif(strpos($val['source'],'user_plan_part_image_save')!==false){
               $val['type'] = 'user';
               $val['source_name'] = '用户生成作品';
           }

           //排队情况
           $val['queue_message'] = '排队中';
           if($val['status']==0){
               $n = 0;
               if($val['type']=='user'){
                   $queueKey = '{redis-queue}-waitingrequestAiImage';
               }else{
                   $queueKey = '{redis-queue}-waitingrequestAiImageAdmin';
               }

               $redisQueues = \Webman\RedisQueue\Redis::connection('ai_image_consumer')->lRange($queueKey,0,-1);
               if($redisQueues){
                   $redisQueues = array_reverse($redisQueues);
                   foreach ($redisQueues as $k=>$q){
                       $qData = json_decode($q, true);
                       if($qData['data']['requestid']==$val['requestid']){
                           $n=($k+1);
                           break;
                       }
                   }
               }
               $n>0 && $val['queue_message'] .= ','.$n.'/'.count($redisQueues);
           }

           $results = json_decode($val['result'], true);
            $val['images1'] = '';
            $val['images2'] = '';
           if(isset($results['images'])){
               $val['images1'] = $results['images'][0]??'';
               $val['images2'] = $results['images'][1]??'';
           }

           $val['param'] = $val['param'] ? json_encode(json_decode($val['param'], true),JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : '';
           $val['result'] = $val['result'] ? json_encode(json_decode($val['result'], true),JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : '';

           if(!empty($val['partid']) && $val['type']=='user'){
              $partids['user'][] = $val['partid'];
           }elseif(!empty($val['partid']) && $val['type']=='admin'){
              $partids['admin'][] = $val['partid'];
           }
        }

        $partsMap = [];
        foreach($partids as $type=>$ids){
            if($type=='user'){
                $partData = UserNovelChapterPartModel::getInstance()->getWhere([['id','in',$ids]])->get()->toArray();
                $userPlanMap = $this->getListMapById(UserPromotionPlanModel::getInstance(),$partData,'user_planid','id');
                foreach ($partData as $part){
                    $part['name'] = $userPlanMap[$part['user_planid']]['name']??'';
                    $partsMap[$type][$part['id']] = $part;
                }
            }elseif($type=='admin'){
                $partData = NovelChapterPartModel::getInstance()->getWhere([['id','in',$ids]])->get()->toArray();
                $planMap = $this->getListMapById(PromotionPlanModel::getInstance(),$partData,'planid','id');
                foreach ($partData as $part){
                    $part['name'] = $planMap[$part['planid']]['name']??'';
                    $partsMap[$type][$part['id']] = $part;
                }
            }
        }

        $commandTemplateMap = $this->getListMapById(ImageCommandPlanModel::getInstance(),$items,'command_template_id','id');
        foreach($items as &$val){
            $val['plan_name'] = '';
            $val['user_sn'] = '';
            if(!empty($val['partid']) && $val['type']=='user'){
                $val['plan_name'] = $partsMap['user'][$val['partid']]['name']??'';
                $val['user_sn'] = $partsMap['user'][$val['partid']]['user_sn']??'';
            }elseif(!empty($val['partid']) && $val['type']=='admin'){
                $val['plan_name'] = $partsMap['admin'][$val['partid']]['name']??'';
            }
            $val['command_template_name'] = isset($commandTemplateMap[$val['command_template_id']]) ? $commandTemplateMap[$val['command_template_id']]['name']:$val['command_template_id'];
        }

        $totalData = $this->getWithdrawTotal();

        return json(['code' => 0, 'msg' => 'ok', 'count' => $total, 'data' => $items, 'total_data' => $totalData]);
    }

    public function getWithdrawTotal()
    {
        $data = [];
        [$where, $format, $limit, $field, $order] = $this->selectInput(request());

        if(isset($where['source']) && is_array($where['source'])){
            $where[] = ['source',$where['source'][0],"%{$where['source'][1]}%"];
            unset($where['source']);
        }
        if(isset($where['status']) && is_array($where['status'])){
            $where[] = ['status',$where['status'][0],$where['status'][1]];
            unset($where['status']);
        }
        if(isset($where['tts']) && is_array($where['tts'])){
            $where[] = ['tts','between',$where['tts']];
            unset($where['tts']);
        }
        if(!empty($where['created_at'])){
            $where[] = ['created_at','between',$where['created_at']];
            unset($where['created_at']);
        }

        if(\request()->input('use_type')=='user'){
            $where[] = ['source', 'like', "user_%"];
        }elseif(\request()->input('use_type')=='admin'){
            $where[] = ['source', 'like', "admin_%"];
        }elseif(\request()->input('use_type')=='cron'){
            $where[] = ['source', 'like', "cron_%"];
        }

        //统计排队中数
        $where1 = $where;
        $where1[] = ['status','=',0];
        $data['status_0_nums'] = $this->model->getWhere($where1)->count();

        //统计失败数
        $where1 = $where;
        $where1[] = ['status','in',[3,4]];
        $data['status_3_nums'] = $this->model->getWhere($where1)->count();

        //统计完成数
        $where1 = $where;
        $where1[] = ['status','=',2];
        $data['status_2_nums'] = $this->model->getWhere($where1)->count();

        //超过30秒数
        $where1 = $where;
        $where1[] = ['tts','>',30];
        $data['greater_than_30_seconds_nums'] = $this->model->getWhere($where1)->count();

        //近10分钟失败数
        $where1 = [];
        $where1[] = ['status','in',[3,4]];
        $where1[] = ['start_time','>=',date('Y-m-d H:i:s',(time()-1800))];
        $data['nearly_30_minutes_fail_nums'] = $this->model->getWhere($where1)->count();

        return $data;
    }
}